<?php
require_once 'phpmoko/lib/common.php';

class Phone
{
	private $phone;
	private $code2;
	private static $regionToCode = array(
		'ac' => '247',
		'ad' => '376',
		'ae' => '971',
		'af' => '93',
		'ag' => '1',
		'ai' => '1',
		'al' => '355',
		'am' => '374',
		'an' => '599',
		'ao' => '244',
		'aq' => '672',
		'ar' => '54',
		'as' => '1',
		'at' => '43',
		'au' => '61',
		'aw' => '297',
		'ax' => '358',
		'az' => '994',
		'ba' => '387',
		'bb' => '1',
		'bd' => '880',
		'be' => '32',
		'bf' => '226',
		'bg' => '359',
		'bh' => '973',
		'bi' => '257',
		'bj' => '229',
		'bl' => '590',
		'bm' => '1',
		'bn' => '673',
		'bo' => '591',
		'bq' => '599',
		'br' => '55',
		'bs' => '1',
		'bt' => '975',
		'bw' => '267',
		'by' => '375',
		'bz' => '501',
		'ca' => '1',
		'cc' => '61',
		'cd' => '243',
		'cf' => '236',
		'cg' => '242',
		'ch' => '41',
		'ci' => '225',
		'ck' => '682',
		'cl' => '56',
		'cm' => '237',
		'cn' => '86',
		'co' => '57',
		'cr' => '506',
		'cu' => '53',
		'cv' => '238',
		'cw' => '599',
		'cx' => '61',
		'cy' => '357',
		'cz' => '420',
		'de' => '49',
		'dj' => '253',
		'dk' => '45',
		'dm' => '1',
		'do' => '1',
		'dz' => '213',
		'ec' => '593',
		'ee' => '372',
		'eg' => '20',
		'eh' => '212',
		'er' => '291',
		'es' => '34',
		'et' => '251',
		'fi' => '358',
		'fj' => '679',
		'fk' => '500',
		'fm' => '691',
		'fo' => '298',
		'fr' => '33',
		'ga' => '241',
		'gb' => '44',
		'gd' => '1',
		'ge' => '995',
		'gf' => '594',
		'gg' => '44',
		'gh' => '233',
		'gi' => '350',
		'gl' => '299',
		'gm' => '220',
		'gn' => '224',
		'gp' => '590',
		'gq' => '240',
		'gr' => '30',
		'gs' => '500',
		'gt' => '502',
		'gu' => '1',
		'gw' => '245',
		'gy' => '592',
		'hk' => '852',
		'hn' => '504',
		'hr' => '385',
		'ht' => '509',
		'hu' => '36',
		'id' => '62',
		'ie' => '353',
		'il' => '972',
		'im' => '44',
		'in' => '91',
		'io' => '246',
		'iq' => '964',
		'ir' => '98',
		'is' => '354',
		'it' => '39',
		'je' => '44',
		'jm' => '1',
		'jo' => '962',
		'jp' => '81',
		'ke' => '254',
		'kg' => '996',
		'kh' => '855',
		'ki' => '686',
		'km' => '269',
		'kn' => '1',
		'kp' => '850',
		'kr' => '82',
		'kw' => '965',
		'ky' => '1',
		'kz' => '7',
		'la' => '856',
		'lb' => '961',
		'lc' => '1',
		'li' => '423',
		'lk' => '94',
		'lr' => '231',
		'ls' => '266',
		'lt' => '370',
		'lu' => '352',
		'lv' => '371',
		'ly' => '218',
		'ma' => '212',
		'mc' => '377',
		'md' => '373',
		'me' => '382',
		'mf' => '590',
		'mg' => '261',
		'mh' => '692',
		'mk' => '389',
		'ml' => '223',
		'mm' => '95',
		'mn' => '976',
		'mo' => '853',
		'mp' => '1',
		'mq' => '596',
		'mr' => '222',
		'ms' => '1',
		'mt' => '356',
		'mu' => '230',
		'mv' => '960',
		'mw' => '265',
		'mx' => '52',
		'my' => '60',
		'mz' => '258',
		'na' => '264',
		'nc' => '687',
		'ne' => '227',
		'nf' => '672',
		'ng' => '234',
		'ni' => '505',
		'nl' => '31',
		'no' => '47',
		'np' => '977',
		'nr' => '674',
		'nu' => '683',
		'nz' => '64',
		'om' => '968',
		'pa' => '507',
		'pe' => '51',
		'pf' => '689',
		'pg' => '675',
		'ph' => '63',
		'pk' => '92',
		'pl' => '48',
		'pm' => '508',
		'pn' => '64',
		'pr' => '1',
		'ps' => '970',
		'pt' => '351',
		'pw' => '680',
		'py' => '595',
		'qa' => '974',
		're' => '262',
		'ro' => '40',
		'rs' => '381',
		'ru' => '7',
		'rw' => '250',
		'sa' => '966',
		'sb' => '677',
		'sc' => '248',
		'sd' => '249',
		'se' => '46',
		'sg' => '65',
		'sh' => '290',
		'si' => '386',
		'sj' => '47',
		'sk' => '421',
		'sl' => '232',
		'sm' => '378',
		'sn' => '221',
		'so' => '252',
		'sr' => '597',
		'ss' => '211',
		'st' => '239',
		'sv' => '503',
		'sx' => '1',
		'sy' => '963',
		'sz' => '268',
		'ta' => '290',
		'tc' => '1',
		'td' => '235',
		'tg' => '228',
		'th' => '66',
		'tj' => '992',
		'tk' => '690',
		'tl' => '670',
		'tm' => '993',
		'tn' => '216',
		'to' => '676',
		'tr' => '90',
		'tt' => '1',
		'tv' => '688',
		'tw' => '886',
		'tz' => '255',
		'ua' => '380',
		'ug' => '256',
		'us' => '1',
		'uy' => '598',
		'uz' => '998',
		'va' => '379',
		'vc' => '1',
		've' => '58',
		'vg' => '1',
		'vi' => '1',
		'vn' => '84',
		'vu' => '678',
		'wf' => '681',
		'ws' => '685',
		'ye' => '967',
		'yt' => '262',
		'za' => '27',
		'zm' => '260',
		'zw' => '263');

	function __construct($phone, $countrycode2)
	{
		$this->code2 = strtolower($countrycode2);
		$this->phone = $this->fixPhone($phone);
	}

	private function startsWith($haystack, $needle)
	{
		return $needle === "" || strpos($haystack, $needle) === 0;
	}

	private function fixPhone($phone)
	{
		$phone = preg_replace('/\D/', '', $phone);

		if (array_key_exists($this->code2, Phone::$regionToCode)) {
			$regionCode = Phone::$regionToCode[$this->code2];
			if ($this->startsWith($phone, '00' . $regionCode))
				$phone = substr($phone, 2 + strlen($regionCode));
			else
				if ($this->startsWith($phone, $regionCode))
					$phone = substr($phone, strlen($regionCode));
		}

		return $phone;
	}

	function getPhone()
	{
		return $this->phone;
	}

	private function convertPhone($phone, $format, $digits)
	{
		if (strlen($phone) != $digits)
			return $phone;

		preg_match($format, $phone, $matches);
		$str = '';
		for ($i = 1; $i < sizeof($matches); $i++) {
			if ($str != '')
				$str .= ' ';
			$str .= $matches[$i];
		}

		return $str;
	}

	function toStringPhone()
	{
		switch ($this->code2) {
			// Brazil
			// (AA) NNNN-NNNN
			// (AA) 9NNNN-NNNN

			case 'br':
				if (strlen($this->phone) < 8)
					break;

				$str = substr($this->phone, -8, 4) . '-' . substr($this->phone, -4, 4);

				if (strlen($this->phone) > 8) {
					$rest = substr($this->phone, 0, -8);
					$last = substr($rest, -1, 1);
					if ($last == '9') {
						$str = $last . $str;
						$rest = substr($rest, 0, -1);
					}

					if (strlen($rest) > 0)
						$str = '(' . $rest . ') ' . $str;
				}

				return $str;
				break;

			// Spain
			// Spanish telephone numbers are nine digits long, starting with '9' or '8' for fixed lines (excluding '90x' and '80x') or with '6' or '7' for mobile phones.
			// The first group in fixes lines always identify the dialed province. That group might be of 2 or 3 digits, for example, 91 and 81 are for Madrid while 925 and 825 are for Toledo. The second group is always of 3 digits as it formerly identified the telephone exchange (now identifies the telephone area).
			// When the first group is 2 digits long (like in Madrid), they are usually written in four groups of 2-3-2-2 digits (AB CCC DD DD)
			// When the first group is 3 digits long (like in Toledo), they are usually written forming 3 groups of 3 digits (ABB CCC DDD) but the form 3-2-2-2 (ABB CC CD DD) is not uncommon.
			// Mobile numbers are usually grouped by threes ABB CCC CCC being the form 3-2-2-2 also seen.
			// Conclusion:
			// Los grupos de 2 digitos se escriben AB CCC DD DD
			// El resto se escribe ABB CCC CCC

			case 'es':
				$p = $this->phone;
				$group = array(
					'93',
					'83',
					'91',
					'81');
				$format = '/(\d{3})(\d{3})(\d{3})/';
				foreach ($group as $code2) {
					if ($this->startsWith($this->phone, $code2)) {
						$format = '/(\d{2})(\d{3})(\d{2})(\d{2})/';
						break;
					}
				}
				return $this->convertPhone($this->phone, $format, 9);
				break;

			// http://en.wikipedia.org/wiki/Telephone_numbers_in_mexico
			case 'mx':
				$p = $this->phone;
				$str = '';
				if (strlen($p) > 10) {
					$str = substr($p, 0, -10) . ' ';
					$p = substr($p, -10);
				}

				if (strlen($p) == 10) {
					$group = array(
						'55',
						'81',
						'33');

					foreach ($group as $code2) {
						if ($this->startsWith($p, $code2)) {
							return $str . substr($p, 0, 2) . ' ' . substr($p, 2, 4) . ' ' . substr($p, 6);
						}
					}

					return $str . substr($p, 0, 3) . ' ' . substr($p, 3, 3) . ' ' . substr($p, 6);
				}

				if (strlen($p) == 8)
					return substr($p, 0, 4) . ' ' . substr($p, 4);

				break;

			// http://en.wikipedia.org/wiki/Telephone_numbers_in_peru
			case 'pe':
				{
					$group = array(
						'1',
						'41',
						'43',
						'83',
						'54',
						'66',
						'76',
						'84',
						'67',
						'62',
						'56',
						'64',
						'44',
						'74',
						'65',
						'82',
						'53',
						'63',
						'73',
						'51',
						'42',
						'52',
						'72',
						'61');

					foreach ($group as $code2) {
						if ($this->startsWith($this->phone, $code2)) {
							$p = substr($this->phone, strlen($code2));
							switch (strlen($p)) {
								case 6:
									return $code2 . ' ' . substr($p, 0, 2) . '-' . substr($p, 2);
								case 7:
									return $code2 . ' ' . substr($p, 0, 3) . ' ' . substr($p, 3);
								default:
									return $code2 . ' ' . $p;
							}
						}
					}

					$p = $this->phone;
					switch (strlen($p)) {
						case 7:
							return substr($p, 0, 1) . ' ' . substr($p, 1, 3) . ' ' . substr($p, 4);
						case 9:
							return substr($p, 0, 3) . ' ' . substr($p, 3, 3) . ' ' . substr($p, 6);
					}
					break;
				}

			// http://en.wikipedia.org/wiki/Telephone_numbers_in_colombia
			case 'co':
				$p = $this->phone;
				switch (strlen($p)) {
					case 7:
						return substr($p, 0, 3) . '-' . substr($p, 3);
					case 8:
						return '(' . substr($p, 0, 1) . ') ' . substr($p, 1, 3) . '-' . substr($p, 4);
					case 10:
						return substr($p, 0, 3) . '-' . substr($p, 3, 3) . '-' . substr($p, 6);
					case 12:
						return substr($p, 0, 2) . '-' . substr($p, 2, 3) . '-' . substr($p, 5, 3) . '-' . substr($p, 8);
				}
				break;

			// http://en.wikipedia.org/wiki/Telephone_numbers_in_El_Salvador
			case 'sv':
				$p = $this->phone;
				switch (strlen($p)) {
					case 7:
						return substr($p, 0, 3) . ' ' . substr($p, 3);
					case 8:
						return substr($p, 0, 4) . ' ' . substr($p, 4);
					case 11:
						return substr($p, 0, 3) . ' ' . substr($p, 3, 4) . ' ' . substr($p, 7);
				}
				break;
		}

		return $this->phone;
	}

	function toStringCountryPhone()
	{
		if (array_key_exists($this->code2, Phone::$regionToCode)) {
			$regionCode = Phone::$regionToCode[$this->code2];

			return '+' . $regionCode . $this->phone;
		}

		return $this->phone;
	}

	function toStringInternationalPhone()
	{
		if (array_key_exists($this->code2, Phone::$regionToCode)) {
			$regionCode = Phone::$regionToCode[$this->code2];

			return '00' . $regionCode . $this->phone;
		}

		return $this->phone;
	}

	function getCountryCode()
	{
		if (array_key_exists($this->code2, Phone::$regionToCode)) {
			$regionCode = Phone::$regionToCode[$this->code2];

			return '+' . $regionCode;
		}

		return '';
	}

	function getInternationalCode()
	{
		if (array_key_exists($this->code2, Phone::$regionToCode)) {
			$regionCode = Phone::$regionToCode[$this->code2];

			return '00' . $regionCode;
		}

		return '';
	}
}
?>